FE-537: Observer agent + entity persistence#23
Conversation
FE-537 Observer agent + entity persistence
After each exchange, fire separate queryStructured call to extract entities. Materialize into decision, assumption, requirement, scope, goal tables. Emit data-entities SSE event. |
Refactors conductTurn into generator composition (D27): interviewer and observer agents are async generators composed via yield*. Shared SDK stream translator in sdk.ts. Observer uses outputFormat for structured JSON extraction (D28). ResultMessage inspection provides per-agent metrics (D29). Observer errors are non-fatal. New: sdk.ts, observer.ts; 147 tests (24 new), all pass. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…established Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
135f857 to
8d6848a
Compare
14e7fd4 to
de355df
Compare
🤖 Augment PR SummarySummary: Adds an “observer” agent that runs after each interview turn to extract/persist decisions & assumptions, and refactors the agent pipeline into composable async generators. Changes:
🤖 Was this summary useful? React with 👍 or 👎 |
| // Parse structured output | ||
| const parsed = observerOutputSchema.parse(resultMessage.structured_output); | ||
|
|
||
| // Persist entities in a transaction-like sequence |
There was a problem hiding this comment.
src/server/observer.ts:L133: This persistence path isn’t actually wrapped in a DB transaction, so a late FK/PK failure (e.g., bad/duplicate parent IDs) can leave partially-created entities/edges while conductTurn() only reports observer-error. That can make the entity graph inconsistent across turns.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| type: 'object', | ||
| properties: { | ||
| content: { type: 'string' }, | ||
| rationale: { type: 'string', nullable: true }, |
There was a problem hiding this comment.
src/server/observer.ts:L93: The outputFormat schema uses nullable: true, which isn’t valid draft-07 JSON Schema (commonly type: ['string','null']) and the Agent SDK docs call for “standard JSON Schema”. If the SDK validates strictly, observer extraction can fail even with otherwise-correct model output.
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
| return [ | ||
| { | ||
| type: 'tool-call-delta', | ||
| toolCallId: toolBlock?.toolCallId ?? '', |
There was a problem hiding this comment.
src/server/sdk.ts:L76: When an input_json_delta arrives without a tracked tool_use block, this emits toolCallId: '', which downstream (SSE + assembleAssistantParts()) can’t associate with a real tool call. If this occurs due to out-of-order/unexpected SDK events, tool-call args may be silently dropped or misattributed.
Severity: low
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.

feat: agent pattern + observer entity persistence (FE-537)
Refactors conductTurn into generator composition (D27): interviewer
and observer agents are async generators composed via yield*.
Shared SDK stream translator in sdk.ts. Observer uses outputFormat
for structured JSON extraction (D28). ResultMessage inspection
provides per-agent metrics (D29). Observer errors are non-fatal.
New: sdk.ts, observer.ts; 147 tests (24 new), all pass.
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com
traceability: slice 5 done — D27/D28/D29, A24/A25 added, I20/I21/I22 established
Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com